﻿using Digitalmes.Model;
using Digitalmes.Model.EquipmentManagement;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;

namespace Digitalmes.Services.Sys
{
    public class AlarmServer : BaseService, IAlarmServer,ISingleton
    {
        
        private readonly IServiceProvider _serviceProvider;
        private readonly List<EquipmentAlarmRecord> _activeAlarms;
      
    
        public AlarmServer( IServiceProvider serviceProvider) : base(serviceProvider)
        {
             
            _serviceProvider = serviceProvider;
            _activeAlarms = new List<EquipmentAlarmRecord>();
          
        }

        public async Task StartAsync()
        {
         

            Log.Information("AlarmServer starting...");

          

            Log.Information("AlarmServer started successfully");
        }

        public async Task StopAsync()
        {
           
            Log.Information("AlarmServer stopping...");

        

            Log.Information("AlarmServer stopped");
        }

        private async void MonitorAlarms(List<EquipmentAlarmItem> items)
        {
           
            try
            {


                // 获取所有激活的设备
                var activeEquipments = await DC.Set<Equipment>()
                    .Where(e => e.Actvie == true && e.IsValid)
                    .Include(e => e.EquipmentTag_Equipment)
                    .Include(e => e.EquipAlarm_Equipment)
                    .ToListAsync();

                foreach (var equipment in activeEquipments)
                {
                    await CheckAlarmConditionsAsync(equipment);
                }
            }
            catch (Exception ex)
            {
                Log.Error("Error monitoring alarms",ex);
            }
        }

        public async Task<bool> CheckAlarmConditionsAsync(Equipment equipment)
        {

            bool alarmTriggered = false;

            // 获取设备的所有激活报警项
            var activeAlarmItems = await DC.Set<EquipmentAlarmItem>()
                .Where(ai => ai.EquipmentId == equipment.ID && ai.Active == true && ai.IsValid)
                .ToListAsync();

            foreach (var alarmItem in activeAlarmItems)
            {
                // 这里需要根据实际的设备驱动和通信协议读取设备变量值
                // 以下为伪代码，实际实现需要根据具体的驱动类型和设备协议
                try
                {
                    var tagValue = await ReadEquipmentTagValue(alarmItem.EquipTagAddress, equipment);

                    // 根据数据类型和报警条件判断是否触发报警
                    if (ShouldTriggerAlarm(tagValue, alarmItem))
                    {
                        await TriggerAlarmAsync(alarmItem, equipment);
                        alarmTriggered = true;
                    }
                }
                catch (Exception ex)
                {
                    Log.Error($"Error checking alarm condition for equipment {equipment.EquipName}, alarm item {alarmItem.ID}",ex);
                }
            }

            return alarmTriggered;
        }

        public async Task<EquipmentAlarmRecord> TriggerAlarmAsync(EquipmentAlarmItem alarmItem, Equipment equipment)
        {

            // 检查是否已有相同设备的相同报警项处于活动状态
            var existingAlarm = await DC.Set<EquipmentAlarmRecord>()
                .FirstOrDefaultAsync(ar =>
                    ar.EquipmentId == equipment.ID &&
                    ar.Address == alarmItem.EquipTagAddress &&
                    ar.Bits == alarmItem.Bits &&
                    ar.Status == AlarmStatusEnum.Doing);

            if (existingAlarm != null)
            {
                // 已存在相同报警，不重复创建
                return existingAlarm;
            }

            // 创建新的报警记录
            var alarmRecord = new EquipmentAlarmRecord
            {
                EquipmentId = equipment.ID,
                Equipment = equipment,
                EquipCode = equipment.EquipCode,
                EquipName = equipment.EquipName,
                Address = alarmItem.EquipTagAddress,
                Bits = alarmItem.Bits,
                Content = alarmItem.Content,
                Level = alarmItem.Level,
                Classify = alarmItem.Classify,
                StartTime = DateTime.Now,
                Status = AlarmStatusEnum.Doing,
                IsValid = true,
                TenantCode = equipment.TenantCode
            };

            DC.Set<EquipmentAlarmRecord>().Add(alarmRecord);
            await DC.SaveChangesAsync();

            _activeAlarms.Add(alarmRecord);

            // 触发报警通知（邮件、短信、App推送等）
            await NotifyAlarm(alarmRecord);

            Log.Warning($"Alarm triggered: {alarmRecord.Content} for equipment {equipment.EquipName}");

            return alarmRecord;
        }

        public async Task<bool> ResolveAlarmAsync(long alarmRecordId)
        {

            var alarmRecord = await DC.Set<EquipmentAlarmRecord>()
                .FirstOrDefaultAsync(ar => ar.ID == alarmRecordId && ar.IsValid);

            if (alarmRecord == null || alarmRecord.Status == AlarmStatusEnum.Close)
            {
                return false;
            }

            alarmRecord.EndTime = DateTime.Now;
            alarmRecord.Status = AlarmStatusEnum.Close;

            if (alarmRecord.StartTime.HasValue)
            {
                alarmRecord.Duration = (decimal)(alarmRecord.EndTime.Value - alarmRecord.StartTime.Value).TotalMinutes;
            }

            await DC.SaveChangesAsync();

            // 从活动报警列表中移除
            _activeAlarms.RemoveAll(ar => ar.ID == alarmRecordId);

            Log.Information($"Alarm resolved: {alarmRecord.Content}");

            return true;
        }

        public List<EquipmentAlarmRecord> GetActiveAlarms()
        {
            return _activeAlarms;
        }

        public List<EquipmentAlarmRecord> GetAlarmHistory(DateTime startTime, DateTime endTime)
        {

            return DC.Set<EquipmentAlarmRecord>()
                .Where(ar => ar.StartTime >= startTime && ar.StartTime <= endTime && ar.IsValid)
                .OrderByDescending(ar => ar.StartTime)
                .ToList();
        }

        // 辅助方法 - 需要根据实际设备驱动实现
        private async Task<object> ReadEquipmentTagValue(string tagAddress, Equipment equipment)
        {
            // 根据设备驱动类型选择不同的读取方式
            switch (equipment.DriverType)
            {
                case DriverTypeEnum.OpcUa:
                    return await ReadOpcUaTagValue(tagAddress, equipment);
                case DriverTypeEnum.SiemensS7:
                    return await ReadS7TagValue(tagAddress, equipment);
                case DriverTypeEnum.ModbusTcp:
                    return await ReadModbusTagValue(tagAddress, equipment);
                // 其他驱动类型...
                default:
                    throw new NotSupportedException($"Driver type {equipment.DriverType} is not supported");
            }
        }

        // 辅助方法 - 判断是否应该触发报警
        private bool ShouldTriggerAlarm(object tagValue, EquipmentAlarmItem alarmItem)
        {
            // 根据报警项的数据类型和报警条件进行判断
            // 这里需要根据实际的数据类型和报警逻辑实现
            // 示例：对于布尔值，通常为true表示报警
            if (tagValue is bool boolValue)
            {
                return boolValue;
            }
            // 对于数值类型，可以检查是否超过阈值等
            // 其他数据类型的处理...

            return false;
        }

        // 辅助方法 - 报警通知
        private async Task NotifyAlarm(EquipmentAlarmRecord alarmRecord)
        {
            // 实现报警通知逻辑，如发送邮件、短信、App推送等
            // 可以根据报警级别决定通知方式和紧急程度
        }

        // 各种设备驱动的具体实现（需要根据实际协议实现）
        private async Task<object> ReadOpcUaTagValue(string tagAddress, Equipment equipment)
        {
            // OPC UA协议实现
            // 返回读取到的标签值
            return null;
        }

        private async Task<object> ReadS7TagValue(string tagAddress, Equipment equipment)
        {
            // Siemens S7协议实现
            // 返回读取到的标签值
            return null;
        }

        private async Task<object> ReadModbusTagValue(string tagAddress, Equipment equipment)
        {
            // Modbus TCP协议实现
            // 返回读取到的标签值
            return null;
        }


    }
}